package com.demo.persistencia.generica.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.compass.core.Compass;
import org.compass.core.CompassCallback;
import org.compass.core.CompassDetachedHits;
import org.compass.core.CompassException;
import org.compass.core.CompassHit;
import org.compass.core.CompassHits;
import org.compass.core.CompassQuery;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.support.search.CompassSearchCommand;
import org.compass.core.support.search.CompassSearchHelper;
import org.compass.core.support.search.CompassSearchResults;
import org.compass.spring.CompassDaoSupport;

import com.demo.persistencia.generica.dao.CompassDao;
import com.demo.persistencia.generica.modelo.ResultsWrapper;


/**
 * Clase destinada a realizar busquedas en los indices lucene.
 */
public class CompassDaoImpl<K extends Serializable> extends  CompassDaoSupport  implements CompassDao<K>{

	
	private static Logger log= Logger.getLogger(CompassDaoImpl.class);
    
    private Compass compass;
   
    
    public CompassDaoImpl() {
    
    }


    
    public void queryString(String queryIndice){
    	int sSeparador =queryIndice.indexOf('#');
    	if(sSeparador!=-1){
    		StringTokenizer tokens = new StringTokenizer(queryIndice,"#");
        	while(tokens.hasMoreTokens()){
        	System.out.println(tokens.nextToken());
        	}
    	}
    }
    
    public List<K> buscarPaginado(String queryIndice, int sizeParametro) {
    	List<K> lstobjetos = new ArrayList<K>();
    	CompassDetachedHits results = null;
        final String query = queryIndice;
        final int from = 0;
        final int size = sizeParametro;
        
        final StringTokenizer tokens = new StringTokenizer(queryIndice,"#");
    	int sSeparador =queryIndice.indexOf('#');
    	if(sSeparador!=-1){
            while(tokens.hasMoreTokens()){System.out.println(tokens.nextToken());}}
        try { System.out.println("query : " +query);
        

        results = getCompassTemplate().execute(new CompassCallback<CompassDetachedHits>() {
            public CompassDetachedHits doInCompass(final CompassSession session) {
                CompassQuery compassQuery = session.queryBuilder().queryString(query).useOrDefaultOperator().toQuery();
                CompassHits activeHits = compassQuery.hits();
                CompassDetachedHits detachedHits = null;
                
                if (activeHits.getLength() > (from + size)) {
                    detachedHits = activeHits.detach(from, size);
                } else if (activeHits.getLength() > from) {
                    detachedHits = activeHits.detach(from, (activeHits.getLength() - from));
                }
                return detachedHits;
            }
        });

   
        if (results != null) {
            for (int i = 0; i < results.getHits().length; i++) {
            	lstobjetos.add((K) results.getHits()[i].getData());
            }
        }

    
        
        } catch (Exception e) {
			e.printStackTrace();
        }

    
        
        return lstobjetos;
    }
    
    
    public ResultsWrapper<K> search(String query, int page, int itemsPage) throws CompassException {
        int pageCompass = 0;
        if (page > 0) {
            pageCompass = page - 1;
        }
        CompassSearchHelper searchHelper = new CompassSearchHelper(compass, itemsPage);
        CompassSearchResults results = searchHelper.search(new CompassSearchCommand(query, pageCompass));
        List<K> itemList = new ArrayList<K>();
        for (CompassHit hit : results.getHits()) {            
            K item = (K) hit.getData();
            itemList.add(item);
        }        
        ResultsWrapper<K> wrapper = new ResultsWrapper<K>();

        wrapper.setTotalResults(results.getTotalHits());        
        wrapper.setResults(itemList);
        
        if (results.getPages() != null && results.getPages().length > 0) {
            wrapper.setTotalPages(results.getPages().length);
            List<Integer> paginator = generatePaginator(results.getPages().length, page);
            wrapper.setPaginator(paginator);
        }
        return wrapper;
    }

    
    public void guardar(final K objeto) {
     super.getCompassTemplate().execute((CompassCallback<K>) new CompassCallback<K>() {

            public K doInCompass(CompassSession session) throws CompassException {
                session.save(objeto);
                log.info("Guardando Objeto : " + objeto.toString());
                return null;
            }
        });
    }
    
    private static List<Integer> generatePaginator(int itemsPage, int pagina) {
        List<Integer> paginatorAux = new ArrayList<Integer>();
        if (itemsPage > 9) {
            if (pagina > 4 && pagina < (itemsPage - 4)) {
                paginatorAux.add(1);
                paginatorAux.add(2);
                paginatorAux.add(-1);
                for (int i = pagina - 2; i <= pagina + 2; i++) {
                    paginatorAux.add(i);
                }
                paginatorAux.add(-1);
                paginatorAux.add(itemsPage - 1);
                paginatorAux.add(itemsPage);
            } else if (pagina >= (itemsPage - 4)) {
                paginatorAux.add(1);
                paginatorAux.add(2);
                paginatorAux.add(-1);
                for (int i = itemsPage - 5; i <= itemsPage; i++) {
                    paginatorAux.add(i);
                }
            } else {
                for (int i = 1; i <= 7; i++) {
                    paginatorAux.add(i);
                }
                paginatorAux.add(-1);
                paginatorAux.add(itemsPage - 1);
                paginatorAux.add(itemsPage);
            }
        } else {
            for (int i = 1; i <= itemsPage; i++) {
                paginatorAux.add(i);
            }
        }
        return paginatorAux;
    }
}
